

#include "xmodule_config.h"


#if MODULE_CHECK_ENABLED( BACKLIGHT )

#include <string.h> 

#include "rtl876x.h"
#include "rtl876x_rcc.h"
#include "rtl876x_gpio.h"
#include "rtl876x_tim.h"
#include "rtl876x_pinmux.h"

#include "em_backlight.h"

#include "boards.h"
#include "xDLPS.h"

#if MODULE_CHECK_LOG_ENABLED( BACKLIGHT )
#include "log.h"
#define LOG     LOG_INFO
#define LOG0    LOG_INFO0 
#define LOG1    LOG_INFO1
#define LOG2    LOG_INFO2
#define LOG3    LOG_INFO3
#else 
#define LOG(...) 
#define LOG0(...)
#define LOG1(...)
#define LOG2(...)
#define LOG3(...)
#endif 

//#define PWM_DUTY                40
#define PWM_HIGH_COUNT          (LCD_BLK_PWM_CYCLE * 50 - 1)
#define PWM_LOW_COUNT           (LCD_BLK_PWM_CYCLE * 50 - 1)

#ifdef ENHANCE_BACKLIGHT_LEVEL
#define PWM_ACTIVE_MAX_LOAD     (LCD_BLK_PWM_CYCLE * 90 / 100) //100=>60 60=>90
#else
#define PWM_ACTIVE_MAX_LOAD     (LCD_BLK_PWM_CYCLE * 100 / 100)
#endif

#define PWM_MAX_LOAD            (LCD_BLK_PWM_CYCLE * 100 / 100)

static uint8_t backlight_dlps_index = 0;
                            
static const T_IO_MODULE_CBS backlight_cbs = 
{
    .init = NULL,
    .enter_dlps = em_backlight_enter_dlps,
    .exit_dlps = em_backlight_exit_dlps,
    .check_allow_dlps = NULL,
    .system_wakeup_check_allow_dlps = NULL,
    .name = "backlight\0",
};
                            

static void gpio_configs(void)
{
//    Pad_Config( LCD_BLK_PWM_PIN, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH );
    Pad_Config( LCD_BLK_PWM_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH );
    
    Pinmux_Config( LCD_BLK_PWM_PIN, LCD_BLK_PWM_TIMER_PIN_PINMUX ); 
    
    RCC_PeriphClockCmd( APBPeriph_TIMER, APBPeriph_TIMER_CLOCK, ENABLE );
    
    TIM_TimeBaseInitTypeDef timInitStruct;    
    
    TIM_StructInit( &timInitStruct );
    timInitStruct.TIM_PWM_En                = PWM_ENABLE;
    timInitStruct.TIM_SOURCE_DIV_En         = ENABLE;
    timInitStruct.TIM_SOURCE_DIV            = TIM_CLOCK_DIVIDER_8; //5Mhz 
    timInitStruct.TIM_Mode                  = TIM_Mode_UserDefine;
    timInitStruct.TIM_PWM_High_Count        = PWM_HIGH_COUNT;
    timInitStruct.TIM_PWM_Low_Count         = PWM_LOW_COUNT;
//    
    TIM_TimeBaseInit( LCD_BLK_PWM_TIMER_NUM, &timInitStruct );
    TIM_Cmd( LCD_BLK_PWM_TIMER_NUM, DISABLE );     
}

void em_backlight_init(void)
{
    gpio_configs();
    em_backlight_set_duty( 50 ); 
//    TIM_Cmd( LCD_BLK_PWM_TIMER_NUM, ENABLE ); 
    

}

void em_backlight_init_dlps(void)
{
    backlight_dlps_index = xDLPS_register( &backlight_cbs );
    LOG1("[BACKLIGHT]: DLPS flag = %d\r\n", backlight_dlps_index );
}

void em_backlight_on(void)
{
    TIM_Cmd( LCD_BLK_PWM_TIMER_NUM, ENABLE ); 
    xDLPS_set( backlight_dlps_index );
}

void em_backlight_off(void)
{
    TIM_Cmd( LCD_BLK_PWM_TIMER_NUM, DISABLE );     
    xDLPS_reset( backlight_dlps_index ); 
}

bool em_backlight_check_duty(uint8_t level)
{
    if( level > LEVEL_OF_BACKLIGHT_ADJUST )
    {
        return false;
    }

    level = MIN_LEVEL_OF_BACKLIGHT + level * STEPS_OF_BACKLIGHT_ADJUST;
    if( level > MAX_LEVEL_OF_BACKLIGHT )
    {
        return false; 
    }
    return true; 
}

void em_backlight_set_duty(uint8_t level)
{
    if( level > LEVEL_OF_BACKLIGHT_ADJUST )
    {
        level = LEVEL_OF_BACKLIGHT_ADJUST;
    }

    level = MIN_LEVEL_OF_BACKLIGHT + level * STEPS_OF_BACKLIGHT_ADJUST;
    if( level > MAX_LEVEL_OF_BACKLIGHT )
    {
        return; 
    }
    uint32_t high =  (PWM_ACTIVE_MAX_LOAD * level / 100) - 1; // (((LCD_BLK_PWM_PERIOD *  duty)  / 100) - 1);
    uint32_t low ;//=  LCD_BLK_PWM_CYCLE * (100 - duty) - 1; //((((LCD_BLK_PWM_PERIOD) * ( 100 - PWM_DUTY)) / 100 ) - 1); 
    
    if( level == 0 ) 
    {
        high = 1; 
    }
    else if (level == 100 ) 
    {
        high = PWM_ACTIVE_MAX_LOAD - 1;
        
    }
    else 
    {
        // use compute result 
    }
    low = PWM_MAX_LOAD - high; 

  LOG2("set_duty_1 high=%d,low=%d",high,low);
   #if BRIGHT_MAX_80
   if((high==80)&&(low==20))
   	{
   	  high=60;
	  low=40;
   	}
   else if((high==60)&&(low==40))
   {
   	  high=45;
	  low=55;
   	}	
   else if((high==40)&&(low==60))
   {
   	  high=30;
	  low=70;
   	}
   else if((high==20)&&(low==80))
   {
   	  high=15;
	  low=85;
   	}
   #endif

	    LOG2("set_duty_2 high=%d,low=%d",high,low);
    TIM_PWMChangeFreqAndDuty( LCD_BLK_PWM_TIMER_NUM, high, low );
}

void em_backlight_enter_dlps(void)
{
    Pad_Config( LCD_BLK_PWM_PIN, PAD_SW_MODE, PAD_NOT_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW ); 
}

void em_backlight_exit_dlps(void)
{
    Pad_Config( LCD_BLK_PWM_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW ); 
}

#endif 
